/**
 *******************************************************************************
 * @file main.c
 * @author .ISS_AUTO (hudandan@issauto.com)
 * @date 2024-05-15  1. Base Version;
 *       2024-09-04  1. Version 0.1.0;
 *       2024-11-19  1. Version 0.2.0;
 *
 * @brief  This file for main.c specification.
 *
 * @copyright Copyright (c) 2024 ISSAUTO TECH Co., Ltd. All rights reserved.
 *
 *******************************************************************************
 */

#define USER_APP

/* Private includes ----------------------------------------------------------*/
#include "main.h"

#include "app_task.h"
#include "cli_task.h"

/* Exported variables --------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#if !defined (USE_TESSY_TEST)
    #define USER_LOOP(test)       for (;;)
#else
    #define USER_LOOP(test)       for (; test;)
#endif

/* Private typedef -----------------------------------------------------------*/
/* Private constants ---------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
static __IO uint16_t sTaskActiveMask;

const iss_sTask_t sTaskTable[TASK_ID_MAX_NUM] = {
    [TASK_ID_APP] = {
        .sTask_Handler = APP_Handle,
    },
    [TASK_ID_CLI] = {
        .sTask_Handler = CLI_Handle,
    },
};

/* Private function prototypes -----------------------------------------------*/
/* Private user code ---------------------------------------------------------*/
/* PRQA S 2740, 2870, 2885, 3383 ++ */

/**
 * @brief Set the Application Timebase Tick object
 * @retval None
 */
void SysTick_TimerCallback(void)
{
    /* TASK_ID_APP */
    APP_TimerCallback();

}

/**
 * @brief Is specified sTask active?
 *
 * @param taskId - sTask to be check.
 */
uint16_t Is_sTask_active(uint16_t taskId)
{
    ISS_ASSERT(taskId < (uint16_t)TASK_ID_MAX_NUM);

    return sTaskActiveMask & (uint16_t)(1UL << taskId);
}

/**
 * @brief Inactive specified sTask.
 *
 * @param taskId - sTask to be disabled.
 */
void sTask_Inactive(uint16_t taskId)
{
    ISS_ASSERT(taskId < (uint16_t)TASK_ID_MAX_NUM);

    sTaskActiveMask &= ~(uint16_t)(1UL << taskId);
}

/**
 * @brief Active specified sTask.
 *
 * @param taskId - sTask to be enabled.
 */
void sTask_Active(uint16_t taskId)
{
    ISS_ASSERT(taskId < (uint16_t)TASK_ID_MAX_NUM);

    sTaskActiveMask |= (uint16_t)(1UL << taskId);
}

/**
 * @brief  The application entry point.
 * @retval int
 */
int main(void)
{
    static __IO uint16_t taskId;

    /* Hardware Initialization */
    SYS_BOARD_INIT();

    /* sTask Initialization */
    // __disable_fiq();

    /* TASK_ID_SYS */
    SYS_Init();

    /* TASK_ID_CLI */
    CLI_Init();

    /* TASK_ID_APP */
    APP_Init();

    sTaskActiveMask = 0;

    for (taskId = 0; taskId < TASK_ID_MAX_NUM; taskId++) {
        sTask_Active(taskId); //!< Default active the sTask.
    }

    // __enable_fiq();


    USER_LOOP(1) {

        /* sTask Handler */
        for (taskId = 0; taskId < TASK_ID_MAX_NUM; taskId++) {
            if (Is_sTask_active(taskId)) {
                if (sTaskTable[taskId].sTask_Handler != NULL) {
                    sTaskTable[taskId].sTask_Handler((void *)&sTaskTable[taskId]);
                }

                sTask_Inactive(taskId); //!< Inactive the sTask.
            }
        }

        /* TASK_ID_SYS */
        SYS_Handle(NULL);

        if (sTaskActiveMask == 0U) {
            #if (LPM_ENABLE)

            /* sTask DeInitialization */

            /* TASK_ID_CLI */
            CLI_DeInit();

            /* TASK_ID_APP */
            APP_DeInit();

            /* TASK_ID_SYS */
            SYS_DeInit();


            /* PWR System Into Sleep */
            #if (LOW_POWER_MODE == STANDBY_MODE)
            USER_PRINTF("\r\n>>> STANDBY\r\n");
            #elif (LOW_POWER_MODE == STOP2_MODE)
            USER_PRINTF("\r\n>>> STOP2\r\n");
            #elif (LOW_POWER_MODE == STOP0_MODE)
            USER_PRINTF("\r\n>>> STOP0\r\n");
            #elif (LOW_POWER_MODE == LOW_POWER_DISABLE)
            USER_PRINTF("\r\n>>> while(1);\r\n");
            #endif
            LOG_LP_Configuration();

            /* WakeUp_Pin Configuration */
            WakeUpPin_Configuration();

            /* Clear WakeUp Flag */
            LPM_FlagClear();

            #if (LOW_POWER_MODE == STANDBY_MODE)
            // DBG_ConfigPeriph(DBG_STDBY, ENABLE);

            /* Enable WKUP pin */
            PWR_WakeUpPinEnable(ENABLE);
            STIMER_mDELAY(5);

            /* Request to enter STANDBY mode */
            PWR_EnterStandbyState();

            /* →→→ SystemReset() ←←← */

            #elif (LOW_POWER_MODE == STOP2_MODE)
            // DBG_ConfigPeriph(DBG_STOP, ENABLE);

            /**
             * @note 进入STOP2后, 除R-SRAM，其他SRAM和寄存器数据都会丢失。
             */

            /* Request to enter STOP2 mode */
            PWR_EnterSTOP2Mode(PWR_STOPENTRY_WFI);

            /* ↓↓↓ WAKEUP ↓↓↓ */

            #elif (LOW_POWER_MODE == STOP0_MODE)
            // DBG_ConfigPeriph(DBG_STOP, ENABLE);

            /* Request to enter STOP0 mode */
            PWR_EnterStopState(PWR_REGULATOR_LOWPOWER, PWR_STOPENTRY_WFI);

            /* ↓↓↓ WAKEUP ↓↓↓ */

            #elif (LOW_POWER_MODE == LOW_POWER_DISABLE)

            while (1) {
                #if (IWDG_ENABLE)
                IWDG_Feed();
                #endif

                if (BKP_ReadBkpData(BKP_REG_ID_WKUP_FLAG) != 0x0000) {
                    break;
                }
            }

            #endif

            User_SystemReset(); //!< Reboot directly!!!
            // SYS_BOARD_INIT();

            #else
            ;
            #endif
        }

    }
}

/* PRQA S 2740, 2870, 2885, 3383 -- */

/* END OF FILE ---------------------------------------------------------------*/
